/*
 * Copyright 2010-2020 Alfresco Software, Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.activiti.engine;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;

import org.activiti.api.runtime.shared.identity.UserGroupManager;
import org.activiti.engine.cfg.MailServerInfo;
import org.activiti.engine.impl.asyncexecutor.AsyncExecutor;
import org.activiti.engine.impl.cfg.BeansConfigurationHelper;
import org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.impl.persistence.entity.integration.IntegrationContextManager;
import org.activiti.engine.integration.IntegrationContextService;
import org.activiti.engine.runtime.Clock;

/**
 * Configuration information from which a process engine can be build.
 *
 * <p>
 * Most common is to create a process engine based on the default configuration file:
 *
 * <pre>
 * ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault().buildProcessEngine();
 * </pre>
 *
 * </p>
 *
 * <p>
 * To create a process engine programmatic, without a configuration file, the first option is {@link #createStandaloneProcessEngineConfiguration()}
 *
 * <pre>
 * ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration().buildProcessEngine();
 * </pre>
 *
 * This creates a new process engine with all the defaults to connect to a remote h2 database (jdbc:h2:tcp://localhost/activiti) in standalone mode. Standalone mode means that Activiti will manage the
 * transactions on the JDBC connections that it creates. One transaction per service method. For a description of how to write the configuration files, see the userguide.
 * </p>
 *
 * <p>
 * The second option is great for testing: {@link #createStandalonInMemeProcessEngineConfiguration()}
 *
 * <pre>
 * ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration().buildProcessEngine();
 * </pre>
 *
 * This creates a new process engine with all the defaults to connect to an memory h2 database (jdbc:h2:tcp://localhost/activiti) in standalone mode. The DB schema strategy default is in this case
 * <code>create-drop</code>. Standalone mode means that Activiti will manage the transactions on the JDBC connections that it creates. One transaction per service method.
 * </p>
 *
 * <p>
 * On all forms of creating a process engine, you can first customize the configuration before calling the {@link #buildProcessEngine()} method by calling any of the setters like this:
 *
 * <pre>
 * ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault().setMailServerHost(&quot;gmail.com&quot;).setJdbcUsername(&quot;mickey&quot;).setJdbcPassword(&quot;mouse&quot;)
 *     .buildProcessEngine();
 * </pre>
 *
 * </p>
 *
 * @see ProcessEngines

 */
public abstract class ProcessEngineConfiguration {

	/**
	 * Checks the version of the DB schema against the library when the process
	 * engine is being created and throws an exception if the versions don't match.
	 */
	public static final String DB_SCHEMA_UPDATE_FALSE = "false";

	/**
	 * Creates the schema when the process engine is being created and drops the
	 * schema when the process engine is being closed.
	 */
	public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";

	/**
	 * Upon building of the process engine, a check is performed and an update of
	 * the schema is performed if it is necessary.
	 */
	public static final String DB_SCHEMA_UPDATE_TRUE = "true";

	/** The tenant id indicating 'no tenant' */
	public static final String NO_TENANT_ID = "";

	protected String processEngineName = ProcessEngines.NAME_DEFAULT;
	protected int idBlockSize = 2500;
	protected String history = HistoryLevel.AUDIT.getKey();
	protected boolean asyncExecutorActivate;

	protected String mailServerHost = "localhost";
	protected String mailServerUsername; // by default no name and password are provided, which
	protected String mailServerPassword; // means no authentication for mail server
	protected int mailServerPort = 25;
	protected boolean useSSL;
	protected boolean useTLS;
	protected String mailServerDefaultFrom = "activiti@localhost";
	protected String mailSessionJndi;
	protected Map<String, MailServerInfo> mailServers = new HashMap<String, MailServerInfo>();
	protected Map<String, String> mailSessionsJndi = new HashMap<String, String>();

	protected String databaseType;
	protected String databaseSchemaUpdate = DB_SCHEMA_UPDATE_FALSE;
	protected String jdbcDriver = "org.h2.Driver";
	protected String jdbcUrl = "jdbc:h2:tcp://localhost/~/activiti";
	protected String jdbcUsername = "sa";
	protected String jdbcPassword = "";
	protected String dataSourceJndiName;
	protected boolean isDbHistoryUsed = true;
	protected HistoryLevel historyLevel;
	protected int jdbcMaxActiveConnections;
	protected int jdbcMaxIdleConnections;
	protected int jdbcMaxCheckoutTime;
	protected int jdbcMaxWaitTime;
	protected boolean jdbcPingEnabled;
	protected String jdbcPingQuery;
	protected int jdbcPingConnectionNotUsedFor;
	protected int jdbcDefaultTransactionIsolationLevel;
	protected DataSource dataSource;
	protected boolean transactionsExternallyManaged;

	protected String jpaPersistenceUnitName;
	protected Object jpaEntityManagerFactory;
	protected boolean jpaHandleTransaction;
	protected boolean jpaCloseEntityManager;

	protected Clock clock;
	protected AsyncExecutor asyncExecutor;
	protected AsyncExecutor asyncPGateExecutor;
	/**
	 * Define the default lock time for an async job in seconds. The lock time is
	 * used when creating an async job and when it expires the async executor
	 * assumes that the job has failed. It will be retried again.
	 */
	protected int lockTimeAsyncJobWaitTime = 60;
	/** define the default wait time for a failed job in seconds */
	protected int defaultFailedJobWaitTime = 10;
	/** define the default wait time for a failed async job in seconds */
	protected int asyncFailedJobWaitTime = 10;

	/**
	 * Allows configuring a database table prefix which is used for all runtime
	 * operations of the process engine. For example, if you specify a prefix named
	 * 'PRE1.', activiti will query for executions in a table named
	 * 'PRE1.ACT_RU_EXECUTION_'.
	 *
	 * <p />
	 * <strong>NOTE: the prefix is not respected by automatic database schema
	 * management. If you use
	 * {@link ProcessEngineConfiguration#DB_SCHEMA_UPDATE_CREATE_DROP} or
	 * {@link ProcessEngineConfiguration#DB_SCHEMA_UPDATE_TRUE}, activiti will
	 * create the database tables using the default names, regardless of the prefix
	 * configured here.</strong>
	 *
	 * @since 5.9
	 */
	protected String databaseTablePrefix = "";

	/**
	 * Escape character for doing wildcard searches.
	 *
	 * This will be added at then end of queries that include for example a LIKE
	 * clause. For example: SELECT * FROM table WHERE column LIKE '%\%%' ESCAPE '\';
	 */
	protected String databaseWildcardEscapeCharacter;

	/**
	 * database catalog to use
	 */
	protected String databaseCatalog = "";

	/**
	 * In some situations you want to set the schema to use for table checks /
	 * generation if the database metadata doesn't return that correctly, see
	 * https://jira.codehaus.org/browse/ACT-1220,
	 * https://jira.codehaus.org/browse/ACT-1062
	 */
	protected String databaseSchema;

	/**
	 * Set to true in case the defined databaseTablePrefix is a schema-name, instead
	 * of an actual table name prefix. This is relevant for checking if
	 * Activiti-tables exist, the databaseTablePrefix will not be used here - since
	 * the schema is taken into account already, adding a prefix for the table-check
	 * will result in wrong table-names.
	 *
	 * @since 5.15
	 */
	protected boolean tablePrefixIsSchema;

	protected String xmlEncoding = "UTF-8";

	protected String defaultCamelContext = "camelContext";

	protected ClassLoader classLoader;
	/**
	 * Either use Class.forName or ClassLoader.loadClass for class loading. See
	 * http://forums.activiti.org/content/reflectutilloadclass-and-custom-
	 * classloader
	 */
	protected boolean useClassForNameClassLoading = true;
	protected ProcessEngineLifecycleListener processEngineLifecycleListener;

	protected boolean enableProcessDefinitionInfoCache = false;
	protected ActivitiEngineAgendaFactory engineAgendaFactory;

	protected boolean copyVariablesToLocalForTasks = false;
	/**是否记录业务方法耗时
	 * 
	 */
	private boolean recordBizSpendTime;
	/**是否开启优化
	 * 
	 */
	private boolean optimized = true;
	
	/** use one of the static createXxxx methods instead */
	protected ProcessEngineConfiguration() {
	}

	public abstract ProcessEngine buildProcessEngine();

	public static ProcessEngineConfiguration createProcessEngineConfigurationFromResourceDefault() {
		return createProcessEngineConfigurationFromResource("activiti.cfg.xml", "processEngineConfiguration");
	}

	public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource) {
		return createProcessEngineConfigurationFromResource(resource, "processEngineConfiguration");
	}

	public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource,
			String beanName) {
		return BeansConfigurationHelper.parseProcessEngineConfigurationFromResource(resource, beanName);
	}

	public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream) {
		return createProcessEngineConfigurationFromInputStream(inputStream, "processEngineConfiguration");
	}

	public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream,
			String beanName) {
		return BeansConfigurationHelper.parseProcessEngineConfigurationFromInputStream(inputStream, beanName);
	}

	public static ProcessEngineConfiguration createStandaloneProcessEngineConfiguration() {
		return new StandaloneProcessEngineConfiguration();
	}

	public static ProcessEngineConfiguration createStandaloneInMemProcessEngineConfiguration() {
		return new StandaloneInMemProcessEngineConfiguration();
	}

	public abstract RepositoryService getRepositoryService();

	public abstract RuntimeService getRuntimeService();

	public abstract TaskService getTaskService();

	public abstract HistoryService getHistoryService();

	public abstract ManagementService getManagementService();

	public abstract ProcessEngineConfiguration getProcessEngineConfiguration();

	public abstract UserGroupManager getUserGroupManager();

	public abstract IntegrationContextService getIntegrationContextService();

	public abstract IntegrationContextManager getIntegrationContextManager();

	// getters and setters
	// //////////////////////////////////////////////////////

	public String getProcessEngineName() {
		return processEngineName;
	}

	public ProcessEngineConfiguration setProcessEngineName(String processEngineName) {
		this.processEngineName = processEngineName;
		return this;
	}

	public int getIdBlockSize() {
		return idBlockSize;
	}

	public ProcessEngineConfiguration setIdBlockSize(int idBlockSize) {
		this.idBlockSize = idBlockSize;
		return this;
	}

	public String getHistory() {
		return history;
	}

	public ProcessEngineConfiguration setHistory(String history) {
		this.history = history;
		return this;
	}

	public String getMailServerHost() {
		return mailServerHost;
	}

	public ProcessEngineConfiguration setMailServerHost(String mailServerHost) {
		this.mailServerHost = mailServerHost;
		return this;
	}

	public String getMailServerUsername() {
		return mailServerUsername;
	}

	public ProcessEngineConfiguration setMailServerUsername(String mailServerUsername) {
		this.mailServerUsername = mailServerUsername;
		return this;
	}

	public String getMailServerPassword() {
		return mailServerPassword;
	}

	public ProcessEngineConfiguration setMailServerPassword(String mailServerPassword) {
		this.mailServerPassword = mailServerPassword;
		return this;
	}

	public String getMailSessionJndi() {
		return mailSessionJndi;
	}

	public ProcessEngineConfiguration setMailSessionJndi(String mailSessionJndi) {
		this.mailSessionJndi = mailSessionJndi;
		return this;
	}

	public int getMailServerPort() {
		return mailServerPort;
	}

	public ProcessEngineConfiguration setMailServerPort(int mailServerPort) {
		this.mailServerPort = mailServerPort;
		return this;
	}

	public boolean getMailServerUseSSL() {
		return useSSL;
	}

	public ProcessEngineConfiguration setMailServerUseSSL(boolean useSSL) {
		this.useSSL = useSSL;
		return this;
	}

	public boolean getMailServerUseTLS() {
		return useTLS;
	}

	public ProcessEngineConfiguration setMailServerUseTLS(boolean useTLS) {
		this.useTLS = useTLS;
		return this;
	}

	public String getMailServerDefaultFrom() {
		return mailServerDefaultFrom;
	}

	public ProcessEngineConfiguration setMailServerDefaultFrom(String mailServerDefaultFrom) {
		this.mailServerDefaultFrom = mailServerDefaultFrom;
		return this;
	}

	public MailServerInfo getMailServer(String tenantId) {
		return mailServers.get(tenantId);
	}

	public Map<String, MailServerInfo> getMailServers() {
		return mailServers;
	}

	public ProcessEngineConfiguration setMailServers(Map<String, MailServerInfo> mailServers) {
		this.mailServers.putAll(mailServers);
		return this;
	}

	public String getMailSessionJndi(String tenantId) {
		return mailSessionsJndi.get(tenantId);
	}

	public Map<String, String> getMailSessionsJndi() {
		return mailSessionsJndi;
	}

	public ProcessEngineConfiguration setMailSessionsJndi(Map<String, String> mailSessionsJndi) {
		this.mailSessionsJndi.putAll(mailSessionsJndi);
		return this;
	}

	public String getDatabaseType() {
		return databaseType;
	}

	public ProcessEngineConfiguration setDatabaseType(String databaseType) {
		this.databaseType = databaseType;
		return this;
	}

	public String getDatabaseSchemaUpdate() {
		return databaseSchemaUpdate;
	}

	public ProcessEngineConfiguration setDatabaseSchemaUpdate(String databaseSchemaUpdate) {
		this.databaseSchemaUpdate = databaseSchemaUpdate;
		return this;
	}

	public DataSource getDataSource() {
		return dataSource;
	}

	public ProcessEngineConfiguration setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
		return this;
	}

	public String getJdbcDriver() {
		return jdbcDriver;
	}

	public ProcessEngineConfiguration setJdbcDriver(String jdbcDriver) {
		this.jdbcDriver = jdbcDriver;
		return this;
	}

	public String getJdbcUrl() {
		return jdbcUrl;
	}

	public ProcessEngineConfiguration setJdbcUrl(String jdbcUrl) {
		this.jdbcUrl = jdbcUrl;
		return this;
	}

	public String getJdbcUsername() {
		return jdbcUsername;
	}

	public ProcessEngineConfiguration setJdbcUsername(String jdbcUsername) {
		this.jdbcUsername = jdbcUsername;
		return this;
	}

	public String getJdbcPassword() {
		return jdbcPassword;
	}

	public ProcessEngineConfiguration setJdbcPassword(String jdbcPassword) {
		this.jdbcPassword = jdbcPassword;
		return this;
	}

	public boolean isTransactionsExternallyManaged() {
		return transactionsExternallyManaged;
	}

	public ProcessEngineConfiguration setTransactionsExternallyManaged(boolean transactionsExternallyManaged) {
		this.transactionsExternallyManaged = transactionsExternallyManaged;
		return this;
	}

	public HistoryLevel getHistoryLevel() {
		return historyLevel;
	}

	public ProcessEngineConfiguration setHistoryLevel(HistoryLevel historyLevel) {
		this.historyLevel = historyLevel;
		return this;
	}

	public boolean isDbHistoryUsed() {
		return isDbHistoryUsed;
	}

	public ProcessEngineConfiguration setDbHistoryUsed(boolean isDbHistoryUsed) {
		this.isDbHistoryUsed = isDbHistoryUsed;
		return this;
	}

	public int getJdbcMaxActiveConnections() {
		return jdbcMaxActiveConnections;
	}

	public ProcessEngineConfiguration setJdbcMaxActiveConnections(int jdbcMaxActiveConnections) {
		this.jdbcMaxActiveConnections = jdbcMaxActiveConnections;
		return this;
	}

	public int getJdbcMaxIdleConnections() {
		return jdbcMaxIdleConnections;
	}

	public ProcessEngineConfiguration setJdbcMaxIdleConnections(int jdbcMaxIdleConnections) {
		this.jdbcMaxIdleConnections = jdbcMaxIdleConnections;
		return this;
	}

	public int getJdbcMaxCheckoutTime() {
		return jdbcMaxCheckoutTime;
	}

	public ProcessEngineConfiguration setJdbcMaxCheckoutTime(int jdbcMaxCheckoutTime) {
		this.jdbcMaxCheckoutTime = jdbcMaxCheckoutTime;
		return this;
	}

	public int getJdbcMaxWaitTime() {
		return jdbcMaxWaitTime;
	}

	public ProcessEngineConfiguration setJdbcMaxWaitTime(int jdbcMaxWaitTime) {
		this.jdbcMaxWaitTime = jdbcMaxWaitTime;
		return this;
	}

	public boolean isJdbcPingEnabled() {
		return jdbcPingEnabled;
	}

	public ProcessEngineConfiguration setJdbcPingEnabled(boolean jdbcPingEnabled) {
		this.jdbcPingEnabled = jdbcPingEnabled;
		return this;
	}

	public String getJdbcPingQuery() {
		return jdbcPingQuery;
	}

	public ProcessEngineConfiguration setJdbcPingQuery(String jdbcPingQuery) {
		this.jdbcPingQuery = jdbcPingQuery;
		return this;
	}

	public int getJdbcPingConnectionNotUsedFor() {
		return jdbcPingConnectionNotUsedFor;
	}

	public ProcessEngineConfiguration setJdbcPingConnectionNotUsedFor(int jdbcPingNotUsedFor) {
		this.jdbcPingConnectionNotUsedFor = jdbcPingNotUsedFor;
		return this;
	}

	public int getJdbcDefaultTransactionIsolationLevel() {
		return jdbcDefaultTransactionIsolationLevel;
	}

	public ProcessEngineConfiguration setJdbcDefaultTransactionIsolationLevel(
			int jdbcDefaultTransactionIsolationLevel) {
		this.jdbcDefaultTransactionIsolationLevel = jdbcDefaultTransactionIsolationLevel;
		return this;
	}

	public boolean isAsyncExecutorActivate() {
		return asyncExecutorActivate;
	}

	public ProcessEngineConfiguration setAsyncExecutorActivate(boolean asyncExecutorActivate) {
		this.asyncExecutorActivate = asyncExecutorActivate;
		return this;
	}

	public ClassLoader getClassLoader() {
		return classLoader;
	}

	public ProcessEngineConfiguration setClassLoader(ClassLoader classLoader) {
		this.classLoader = classLoader;
		return this;
	}

	public boolean isUseClassForNameClassLoading() {
		return useClassForNameClassLoading;
	}

	public ProcessEngineConfiguration setUseClassForNameClassLoading(boolean useClassForNameClassLoading) {
		this.useClassForNameClassLoading = useClassForNameClassLoading;
		return this;
	}

	public Object getJpaEntityManagerFactory() {
		return jpaEntityManagerFactory;
	}

	public ProcessEngineConfiguration setJpaEntityManagerFactory(Object jpaEntityManagerFactory) {
		this.jpaEntityManagerFactory = jpaEntityManagerFactory;
		return this;
	}

	public boolean isJpaHandleTransaction() {
		return jpaHandleTransaction;
	}

	public ProcessEngineConfiguration setJpaHandleTransaction(boolean jpaHandleTransaction) {
		this.jpaHandleTransaction = jpaHandleTransaction;
		return this;
	}

	public boolean isJpaCloseEntityManager() {
		return jpaCloseEntityManager;
	}

	public ProcessEngineConfiguration setJpaCloseEntityManager(boolean jpaCloseEntityManager) {
		this.jpaCloseEntityManager = jpaCloseEntityManager;
		return this;
	}

	public String getJpaPersistenceUnitName() {
		return jpaPersistenceUnitName;
	}

	public ProcessEngineConfiguration setJpaPersistenceUnitName(String jpaPersistenceUnitName) {
		this.jpaPersistenceUnitName = jpaPersistenceUnitName;
		return this;
	}

	public String getDataSourceJndiName() {
		return dataSourceJndiName;
	}

	public ProcessEngineConfiguration setDataSourceJndiName(String dataSourceJndiName) {
		this.dataSourceJndiName = dataSourceJndiName;
		return this;
	}

	public String getDefaultCamelContext() {
		return defaultCamelContext;
	}

	public ProcessEngineConfiguration setDefaultCamelContext(String defaultCamelContext) {
		this.defaultCamelContext = defaultCamelContext;
		return this;
	}

	public ProcessEngineConfiguration setProcessEngineLifecycleListener(
			ProcessEngineLifecycleListener processEngineLifecycleListener) {
		this.processEngineLifecycleListener = processEngineLifecycleListener;
		return this;
	}

	public ProcessEngineLifecycleListener getProcessEngineLifecycleListener() {
		return processEngineLifecycleListener;
	}

	public String getDatabaseTablePrefix() {
		return databaseTablePrefix;
	}

	public ProcessEngineConfiguration setDatabaseTablePrefix(String databaseTablePrefix) {
		this.databaseTablePrefix = databaseTablePrefix;
		return this;
	}

	public ProcessEngineConfiguration setTablePrefixIsSchema(boolean tablePrefixIsSchema) {
		this.tablePrefixIsSchema = tablePrefixIsSchema;
		return this;
	}

	public boolean isTablePrefixIsSchema() {
		return tablePrefixIsSchema;
	}

	public String getDatabaseWildcardEscapeCharacter() {
		return databaseWildcardEscapeCharacter;
	}

	public ProcessEngineConfiguration setDatabaseWildcardEscapeCharacter(String databaseWildcardEscapeCharacter) {
		this.databaseWildcardEscapeCharacter = databaseWildcardEscapeCharacter;
		return this;
	}

	public String getDatabaseCatalog() {
		return databaseCatalog;
	}

	public ProcessEngineConfiguration setDatabaseCatalog(String databaseCatalog) {
		this.databaseCatalog = databaseCatalog;
		return this;
	}

	public String getDatabaseSchema() {
		return databaseSchema;
	}

	public ProcessEngineConfiguration setDatabaseSchema(String databaseSchema) {
		this.databaseSchema = databaseSchema;
		return this;
	}

	public String getXmlEncoding() {
		return xmlEncoding;
	}

	public ProcessEngineConfiguration setXmlEncoding(String xmlEncoding) {
		this.xmlEncoding = xmlEncoding;
		return this;
	}

	public Clock getClock() {
		return clock;
	}

	public ProcessEngineConfiguration setClock(Clock clock) {
		this.clock = clock;
		return this;
	}

	public AsyncExecutor getAsyncExecutor() {
		return asyncExecutor;
	}

	public AsyncExecutor getAsyncPGateExecutor() {
		return asyncPGateExecutor;
	}

	public ProcessEngineConfiguration setAsyncExecutor(AsyncExecutor asyncExecutor) {
		this.asyncExecutor = asyncExecutor;
		return this;
	}

	public ProcessEngineConfiguration setAsyncPGateExecutor(AsyncExecutor asyncPGateExecutor) {
		this.asyncPGateExecutor = asyncPGateExecutor;
		return this;
	}

	public int getLockTimeAsyncJobWaitTime() {
		return lockTimeAsyncJobWaitTime;
	}

	public ProcessEngineConfiguration setLockTimeAsyncJobWaitTime(int lockTimeAsyncJobWaitTime) {
		this.lockTimeAsyncJobWaitTime = lockTimeAsyncJobWaitTime;
		return this;
	}

	public int getDefaultFailedJobWaitTime() {
		return defaultFailedJobWaitTime;
	}

	public ProcessEngineConfiguration setDefaultFailedJobWaitTime(int defaultFailedJobWaitTime) {
		this.defaultFailedJobWaitTime = defaultFailedJobWaitTime;
		return this;
	}

	public int getAsyncFailedJobWaitTime() {
		return asyncFailedJobWaitTime;
	}

	public ProcessEngineConfiguration setAsyncFailedJobWaitTime(int asyncFailedJobWaitTime) {
		this.asyncFailedJobWaitTime = asyncFailedJobWaitTime;
		return this;
	}

	public boolean isEnableProcessDefinitionInfoCache() {
		return enableProcessDefinitionInfoCache;
	}

	public ProcessEngineConfiguration setEnableProcessDefinitionInfoCache(boolean enableProcessDefinitionInfoCache) {
		this.enableProcessDefinitionInfoCache = enableProcessDefinitionInfoCache;
		return this;
	}

	public ProcessEngineConfiguration setCopyVariablesToLocalForTasks(boolean copyVariablesToLocalForTasks) {
		this.copyVariablesToLocalForTasks = copyVariablesToLocalForTasks;
		return this;
	}

	public boolean isCopyVariablesToLocalForTasks() {
		return copyVariablesToLocalForTasks;
	}

	public void setEngineAgendaFactory(ActivitiEngineAgendaFactory engineAgendaFactory) {
		this.engineAgendaFactory = engineAgendaFactory;
	}

	public ActivitiEngineAgendaFactory getEngineAgendaFactory() {
		return engineAgendaFactory;
	}

	public boolean isRecordBizSpendTime() {
		return recordBizSpendTime;
	}

	public void setRecordBizSpendTime(boolean recordBizSpendTime) {
		this.recordBizSpendTime = recordBizSpendTime;
	}

	public boolean isOptimized() {
		return optimized;
	}

	public void setOptimized(boolean optimized) {
		this.optimized = optimized;
	}

}
